package gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JSeparator;
import javax.swing.JTabbedPane;
import javax.swing.filechooser.FileNameExtensionFilter;

import kernel.AsuvizCore;
import kernel.FiberSet;
import renderer.AsuVizRendererCore;
import util.IniFilesReader;

public class MainFrame extends JFrame implements ActionListener{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private AsuVizRendererCore rendererCore;
	private PanelRenderer panelRenderer;

	private static final String ACTION_LOAD_CONIFG_FILE = "ACTION_LOAD_CONFIG_FILE";
	private static final String ACTION_CLOSE = "ACTION_CLOSE";
	private static final String ACTION_WRITE_CSV_FILE = "ACTION_WRITE_CSV_FILE";
	private static final String ACTION_CREATE_NEW_FIBER = "CREATE_NEW_FIBER";
	private static final String ACTION_GENERATE_ROI_MATRIX = "GENERATE_ROI_MATRIX";

	private JMenuBar menuBar;
	private JMenu menuFile;
	private JMenuItem menuFileOpen;
	private JMenuItem menuFileClose;

	private JMenu menuEdit;
	private JMenuItem menuEditWriteFile;
	private JMenuItem menuEditCreateFiber;
	private JMenuItem menuEditGenerateRoiMatrix;

	private PanelConfiguration panelConfiguration;
	private JTabbedPane tabbedPane;
	
	private String lastVTKDirectory = "File";

	public MainFrame()
	{
		menuBar = new JMenuBar();
		setJMenuBar(menuBar);

		menuFile = new JMenu("File");

		menuFileOpen = new JMenuItem("Open Config file");
		menuFileOpen.setActionCommand(ACTION_LOAD_CONIFG_FILE);
		menuFileOpen.addActionListener(this);

		menuFileClose = new JMenuItem("Close");
		menuFileClose.setActionCommand(ACTION_CLOSE);
		menuFileClose.addActionListener(this);

		menuFile.add(menuFileOpen);
		menuFile.add(new JSeparator());
		menuFile.add(menuFileClose);

		menuBar.add(menuFile);

		menuEdit = new JMenu("Edit");

		menuEditWriteFile = new JMenuItem("Write File");
		menuEditWriteFile.setActionCommand(ACTION_WRITE_CSV_FILE);
		menuEditWriteFile.addActionListener(this);
		menuEditWriteFile.setEnabled(false);
		menuEdit.add(menuEditWriteFile);

		menuEditCreateFiber = new JMenuItem("Create new fiber from CSV file");
		menuEditCreateFiber.setActionCommand(ACTION_CREATE_NEW_FIBER);
		menuEditCreateFiber.addActionListener(this);
		menuEditCreateFiber.setEnabled(false);
		menuEdit.add(menuEditCreateFiber);

		menuEditGenerateRoiMatrix = new JMenuItem("Generate ROI Matrix");
		menuEditGenerateRoiMatrix.setActionCommand(ACTION_GENERATE_ROI_MATRIX);
		menuEditGenerateRoiMatrix.addActionListener(this);
		menuEditGenerateRoiMatrix.setEnabled(false);
		//		menuEdit.add(menuEditGenerateRoiMatrix);

		menuBar.add(menuEdit);

		panelConfiguration = new PanelConfiguration(this);

		rendererCore = new AsuVizRendererCore();
//
//		panelRenderer = new PanelRenderer(rendererCore.getCanvas());
		panelRenderer = new PanelRenderer();
		panelRenderer.setVisible(true);

		setSize(800,800);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setLayout(new BorderLayout());
		
		tabbedPane = new JTabbedPane();
		tabbedPane.add("Configuration", panelConfiguration);
		tabbedPane.add("Renderer", panelRenderer);
		
		add(tabbedPane, BorderLayout.CENTER);
		setVisible(true);
//		setResizable(false);
	}

	public static void main(String[] args)
	{
		new MainFrame();
	}

	public void loadFiberSetSetups(ArrayList<FiberSetSetup> setups)
	{
		menuEditWriteFile.setEnabled(true);
		menuEditCreateFiber.setEnabled(true);
		menuEditGenerateRoiMatrix.setEnabled(true);
		for(FiberSetSetup fss : setups)
		{
			Map<Integer, Object> params = new HashMap<Integer, Object>();
			params.put(FiberSet.FILEPATH, fss.getFilepath());
			params.put(FiberSet.COLOR, fss.getColor());
			params.put(FiberSet.RENDER_COUNT, fss.getRenderCount());
			params.put(FiberSet.RENDER_TYPE, fss.getRenderType());
			try {
				AsuvizCore.getInstance().addFiberSet(params);
				fss.setLoaded();
				panelConfiguration.update();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		rendererCore.setFiberSetIndex(AsuvizCore.getInstance().getFiberSetIndex());

	}
	
	public void loadVolumes()
	{
//		rendererCore.
	}
	
	public void processFibers()
	{
		String[] renderOptions = new String[]{"Render Fibers", "Render ROI Matrix", "Render Connectivity Matrix 3D", "Save Connectivity Matrix 2D File", "Save connectivy file (ROIS, fibers, ids, counter)", "Save Connectivity Matrix Binary 2D File"};
		String selectedOption = (String)JOptionPane.showInputDialog(this, "Select Processing option", "", JOptionPane.INFORMATION_MESSAGE, null, renderOptions, renderOptions[0]);
		if(selectedOption != null)
		{
			if(selectedOption.equals(renderOptions[0]))
			{
				panelRenderer.setCanvas(rendererCore.getCanvas());
				tabbedPane.setSelectedIndex(1);
				rendererCore.renderFibers();		
			}
			else if(selectedOption.equals(renderOptions[1]))
			{
				ArrayList<FiberSetSetup> fiberSets = panelConfiguration.getFiberSets();
				String[] fiberList = new String[fiberSets.size()];
				for(int i = 0;  i < fiberSets.size(); i++)
				{
					fiberList[i] = fiberSets.get(i).getName();
				}
				String selectedFiber = (String)JOptionPane.showInputDialog(this, "Select fiber", "", JOptionPane.INFORMATION_MESSAGE, null, fiberList, fiberList[0]);
				if(selectedFiber != null)
				{
					String roiResolutionString = JOptionPane.showInputDialog(this, "Resolution in mm");
					if(roiResolutionString != null)
					{
						double roiResolution = Double.parseDouble(roiResolutionString);
						AsuvizCore.getInstance().generateRoiMatrix(selectedFiber, roiResolution);

						int[][][] roiMatrix = AsuvizCore.getInstance().getCounterRoiMatrix(selectedFiber);
						int max = AsuvizCore.getInstance().getCounterRoiMax(selectedFiber);
						panelRenderer.setCanvas(rendererCore.getCanvas());
						tabbedPane.setSelectedIndex(1);
						rendererCore.renderRoiIntegerMatrix(roiMatrix, max);
					}
				}
			}
			else if(selectedOption.equals(renderOptions[2]))
			{
				ArrayList<FiberSetSetup> fiberSets = panelConfiguration.getFiberSets();
				String[] fiberList = new String[fiberSets.size()];
				for(int i = 0;  i < fiberSets.size(); i++)
				{
					fiberList[i] = fiberSets.get(i).getName();
				}
				String selectedFiber = (String)JOptionPane.showInputDialog(this, "Select fiber", "", JOptionPane.INFORMATION_MESSAGE, null, fiberList, fiberList[0]);
				if(selectedFiber != null)
				{
					String roiResolutionString = JOptionPane.showInputDialog(this, "Resolution in mm");
					if(roiResolutionString != null)
					{
						double roiResolution = Double.parseDouble(roiResolutionString);
						AsuvizCore.getInstance().generateRoiMatrix(selectedFiber, roiResolution);
						AsuvizCore.getInstance().calculateConnectivityRoiMatrix(selectedFiber);
						int[][][] roiMatrix = AsuvizCore.getInstance().getConnectivityCounterRoiMatrix(selectedFiber);
						
//						int[][][] roiMatrix = AsuvizCore.getInstance().getROIMatrixForFiber(selectedFiber, 0);
						int max = AsuvizCore.getInstance().getConnectivityCounterRoiMax(selectedFiber);
						rendererCore.renderRoiIntegerMatrix(roiMatrix, max);
					}
				}
			}
			else if(selectedOption.equals(renderOptions[3]))
			{
				ArrayList<FiberSetSetup> fiberSets = panelConfiguration.getFiberSets();
				String[] fiberList = new String[fiberSets.size()];
				for(int i = 0;  i < fiberSets.size(); i++)
				{
					fiberList[i] = fiberSets.get(i).getName();
				}
				String selectedFiber = (String)JOptionPane.showInputDialog(this, "Select fiber", "", JOptionPane.INFORMATION_MESSAGE, null, fiberList, fiberList[0]);
				if(selectedFiber != null)
				{
					String roiResolutionString = JOptionPane.showInputDialog(this, "Resolution in mm");
					if(roiResolutionString != null)
					{
						double roiResolution = Double.parseDouble(roiResolutionString);
						AsuvizCore.getInstance().generateRoiMatrix(selectedFiber, roiResolution);
						AsuvizCore.getInstance().calculateConnectivityRoiMatrix(selectedFiber);
						
						JFileChooser fileChooser = new JFileChooser("File");
						int option = fileChooser.showSaveDialog(this);
						if(option == JFileChooser.APPROVE_OPTION)
						{
							AsuvizCore.getInstance().calculateConnectivity2DMatrix(selectedFiber, fileChooser.getSelectedFile(), 0, 0, 0, FiberSet.PRINT_2D_MATRIX);	
							try {
								AsuvizCore.getInstance().writeConnectivityMatrix(selectedFiber, fileChooser.getSelectedFile(), 0, 0, 0, false);
							} catch (Exception e) {
								e.printStackTrace();
							}
							
						}
					}
				}
				
			}
			else if(selectedOption.equals(renderOptions[4]))
			{
				ArrayList<FiberSetSetup> fiberSets = panelConfiguration.getFiberSets();
				String[] fiberList = new String[fiberSets.size()];
				for(int i = 0;  i < fiberSets.size(); i++)
				{
					fiberList[i] = fiberSets.get(i).getName();
				}
				String selectedFiber = (String)JOptionPane.showInputDialog(this, "Select fiber", "", JOptionPane.INFORMATION_MESSAGE, null, fiberList, fiberList[0]);
				if(selectedFiber != null)
				{
					String roiResolutionString = JOptionPane.showInputDialog(this, "Resolution in mm");
					if(roiResolutionString != null)
					{
						double roiResolution = Double.parseDouble(roiResolutionString);
						AsuvizCore.getInstance().generateRoiMatrix(selectedFiber, roiResolution);
						AsuvizCore.getInstance().calculateConnectivityRoiMatrix(selectedFiber);
						
						JFileChooser fileChooser = new JFileChooser("File");
						int option = fileChooser.showSaveDialog(this);
						if(option == JFileChooser.APPROVE_OPTION)
						{
							AsuvizCore.getInstance().calculateConnectivity2DMatrix(selectedFiber, fileChooser.getSelectedFile(), 0, 0, 0, FiberSet.PRINT_CONNECTIVITY_FILE);	
						}
					}
				}
				
			}
			else 
			{
				JOptionPane.showMessageDialog(this, "Under Construction");
//				ArrayList<FiberSetSetup> fiberSets = panelConfiguration.getFiberSets();
//				String[] fiberList = new String[fiberSets.size()];
//				for(int i = 0;  i < fiberSets.size(); i++)
//				{
//					fiberList[i] = fiberSets.get(i).getName();
//				}
//				String selectedFiber = (String)JOptionPane.showInputDialog(this, "Select fiber", "", JOptionPane.INFORMATION_MESSAGE, null, fiberList, fiberList[0]);
//				if(selectedFiber != null)
//				{
//					String roiResolutionString = JOptionPane.showInputDialog(this, "Resolution in mm");
//					if(roiResolutionString != null)
//					{
//						try {
//							double roiResolution = Double.parseDouble(roiResolutionString);
//							AsuvizCore.getInstance().generateRoiMatrix(selectedFiber, roiResolution);
//							AsuvizCore.getInstance().calculateConnectivityRoiMatrix(selectedFiber);
//							AsuvizCore.getInstance().calculateConnectivity2DMatrix(selectedFiber, 0, 0, 0);
//							int[][] connectivityMatrix = AsuvizCore.getInstance().get2DIntegerConnectivityMatrix(selectedFiber);
//							int max = AsuvizCore.getInstance().getConnectivityMatrixMax(selectedFiber);
//							
//							String[] thresholdOptions = new String[max];
//							for(int i = 0; i<max; i++)
//							{
//								thresholdOptions[i] = "" + (i + 1);
//							}
//							String selectedThreshold = (String)JOptionPane.showInputDialog(this, "Select threshold", "", JOptionPane.INFORMATION_MESSAGE, null, thresholdOptions, thresholdOptions[0]);
//							int threshold = 0;
//							if(selectedThreshold != null)
//							{
//								threshold = Integer.parseInt(selectedThreshold);
//								JFileChooser fileChooser = new JFileChooser("File");
//								int option = fileChooser.showSaveDialog(this);
//								if(option == JFileChooser.APPROVE_OPTION)
//								{
//									AsuvizCore.getInstance().writeConnectivityMatrixBinary(connectivityMatrix, threshold, fileChooser.getSelectedFile());
//								}	
//							}
//						}catch (Exception e) {
//							e.printStackTrace();
//						}
//					}
//				}
			}
		}
	}

	private void addFiberSetsFromConfigFile(String filePath) throws Exception
	{
		Map<String, String> asuvizParams = IniFilesReader.readIniFile(filePath);
		int fibersetCount = Integer.parseInt(asuvizParams.get("fiberset.count"));
		for(int i = 0; i < fibersetCount; i++)
		{
			String fibersetFilepath = asuvizParams.get("fiberset."+i+".filepath");
			int red = Integer.parseInt(asuvizParams.get("fiberset."+i+".r"));
			int green = Integer.parseInt(asuvizParams.get("fiberset."+i+".g"));
			int blue = Integer.parseInt(asuvizParams.get("fiberset."+i+".b"));
			Color fiberColor = new Color(red,  green, blue);
			int fiberRenderCount = Integer.parseInt(asuvizParams.get("fiberset."+i+".render.count"));
			String fiberRenderType = (asuvizParams.get("fiberset."+i+".render.type"));

			FiberSetSetup fiberSetSetup = new FiberSetSetup(fibersetFilepath, fiberColor, fiberRenderCount, FiberSetSetup.getRenderType(fiberRenderType));
			panelConfiguration.addFiberSetSetup(fiberSetSetup);
		}
		panelConfiguration.update();
	}

	@Override
	public void actionPerformed(ActionEvent actionEvent) {
		String actionCommand = actionEvent.getActionCommand();
		if(actionCommand.equals(ACTION_LOAD_CONIFG_FILE))
		{
			JFileChooser fileChooser = new JFileChooser("File");
			fileChooser.setFileFilter(new FileNameExtensionFilter("Configuration Files", new String[]{"config"}));
			int option = fileChooser.showOpenDialog(this);
			if(option == JFileChooser.APPROVE_OPTION)
			{
				try {
					String filePath = fileChooser.getSelectedFile().getAbsolutePath();
					addFiberSetsFromConfigFile(filePath);
					panelConfiguration.enableRenderButton(true);
				} catch (Exception e) {
					e.printStackTrace();
					JOptionPane.showMessageDialog(this, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
				}
			}
		}
		else if(actionCommand.equals(ACTION_WRITE_CSV_FILE))
		{
			ArrayList<FiberSetSetup> fiberSets = panelConfiguration.getFiberSets();
			String[] fiberList = new String[fiberSets.size() + 1];
			fiberList[0] = "All Fibers";
			for(int i = 0;  i < fiberSets.size(); i++)
			{
				fiberList[i + 1] = fiberSets.get(i).getName();
			}
			String selectedFiber = (String)JOptionPane.showInputDialog(this, "Select fiber", "", JOptionPane.INFORMATION_MESSAGE, null, fiberList, fiberList[0]);
			if(selectedFiber != null)
			{
				if(selectedFiber.equals("All Fibers"))
				{
					JFileChooser fileChooser = new JFileChooser("File");
					fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
					int fileOption = fileChooser.showSaveDialog(this);
					if(fileOption == JFileChooser.APPROVE_OPTION)
					{
						File selectedDirectory = fileChooser.getSelectedFile();
						try {
							AsuvizCore.getInstance().writeAllFiberFiles(selectedDirectory);
						} catch (Exception e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
				}
				else
				{
					JFileChooser fileChooser = new JFileChooser("File");
					int fileOption = fileChooser.showSaveDialog(this);
					if(fileOption == JFileChooser.APPROVE_OPTION)
					{
						try {
							AsuvizCore.getInstance().writeFiberFile(selectedFiber, fileChooser.getSelectedFile());
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
				}

			}
		}
		else if(actionCommand.equals(ACTION_CREATE_NEW_FIBER))
		{
			ArrayList<FiberSetSetup> fiberSets = panelConfiguration.getFiberSets();
			String[] fiberList = new String[fiberSets.size() + 1];
			fiberList[0] = "Batch";
			for(int i = 0;  i < fiberSets.size(); i++)
			{
				fiberList[i + 1] = fiberSets.get(i).getName();
			}
			String selectedFiber = (String)JOptionPane.showInputDialog(this, "Select fiber", "", JOptionPane.INFORMATION_MESSAGE, null, fiberList, fiberList[0]);
			if(selectedFiber != null)
			{
				if(selectedFiber.equals("Batch"))
				{
					JFileChooser fileChooser = new JFileChooser(lastVTKDirectory);
					fileChooser.setMultiSelectionEnabled(true);
					fileChooser.setFileFilter(new FileNameExtensionFilter("CSV Files", new String[]{"csv"}));
					int fileOption = fileChooser.showOpenDialog(this);
					if(fileOption == JFileChooser.APPROVE_OPTION)
					{
						File[] selectedFiles = fileChooser.getSelectedFiles();
						int createdFiles = 0;
						for(File file : selectedFiles)
						{
							try {
								String fiberName = file.getAbsolutePath();
								fiberName = fiberName.substring(fiberName.lastIndexOf(File.separatorChar), fiberName.lastIndexOf("."));
								AsuvizCore.getInstance().createFiberFromFile(file, fiberName);
								AsuvizCore.getInstance().createVTK(fiberName);
								createdFiles++;
								System.out.println(createdFiles + " files created out of " + selectedFiles.length);
							} catch (Exception e) {
								e.printStackTrace();
							}
						}
						JOptionPane.showMessageDialog(this, createdFiles + " files created from " + selectedFiles.length + " CSV Files");
					}
				}
				else
				{
					JFileChooser fileChooser = new JFileChooser(lastVTKDirectory);
					fileChooser.setFileFilter(new FileNameExtensionFilter("CSV Files", new String[]{"csv"}));
					int fileOption = fileChooser.showOpenDialog(this);
					if(fileOption == JFileChooser.APPROVE_OPTION)
					{
						try {
							AsuvizCore.getInstance().createFiberFromFile(fileChooser.getSelectedFile(), selectedFiber);
							AsuvizCore.getInstance().createVTK(selectedFiber);
//							rendererCore.addNewFiberSet(selectedFiber);
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
				}
			}
		}
		else if(actionCommand.equals(ACTION_GENERATE_ROI_MATRIX))
		{
			ArrayList<FiberSetSetup> fiberSets = panelConfiguration.getFiberSets();
			String[] fiberList = new String[fiberSets.size()];
			for(int i = 0;  i < fiberSets.size(); i++)
			{
				fiberList[i] = fiberSets.get(i).getName();
			}
			String selectedFiber = (String)JOptionPane.showInputDialog(this, "Select fiber", "", JOptionPane.INFORMATION_MESSAGE, null, fiberList, fiberList[0]);
			if(selectedFiber != null)
			{
				String roiResolutionString = JOptionPane.showInputDialog(this, "Resolution in mm");
				if(roiResolutionString != null)
				{
					double roiResolution = Double.parseDouble(roiResolutionString);
					AsuvizCore.getInstance().generateRoiMatrix(selectedFiber, roiResolution);

					int[][][] roiMatrix = AsuvizCore.getInstance().getCounterRoiMatrix(selectedFiber);
					int max = AsuvizCore.getInstance().getCounterRoiMax(selectedFiber);
					rendererCore.renderRoiIntegerMatrix(roiMatrix, max);

				}
			}
		}
		else if(actionCommand.equals(ACTION_CLOSE))
		{
			System.exit(0);
		}
	}
	
	public void setLastVTKDirectory(String directory)
	{
		lastVTKDirectory = directory + File.separatorChar;
	}
	
	public String getLastVTKDirectory()
	{
		return lastVTKDirectory;
	}

}
